About this file Data Fields:

library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(ggplot2)
library(tidyr)
library(car)
Loading required package: carData

Attaching package: ‘car’

The following object is masked from ‘package:dplyr’:

    recode
library(MASS)

Attaching package: ‘MASS’

The following object is masked from ‘package:dplyr’:

    select
library(repr)

library(pals)
ecars_raw = read.csv('EV_cars.csv')
ecars_raw
NA
#rename some of the columns
ecars_raw = ecars_raw %>% rename(Price = Price.DE., Acceleration = acceleration..0.100.)

# extract the Make of each car into its own column
make = strsplit(ecars_raw$Car_name, split = ' ')

make_ = c()
n = length(make)

for (i in 1:n) {
  make_[i] = make[[i]][1]
}

ecars_raw$Make = make_
# move columns so continuous variables are together 
ecars_raw = ecars_raw %>% relocate(Make, .before = Car_name_link)
ecars_raw = ecars_raw %>% relocate(Battery, .after = Car_name_link)
ecars_raw
ecars_raw = ecars_raw %>% filter(!is.na(Fast_charge))
ecars = ecars_raw %>% filter(!is.na(Price))
ecars_missing_price = ecars_raw %>% filter(is.na(Price))

This data required minimal processing. I created a Make variable by extracting the first word from the Car_name variable. I also renamed several columns to make them more intuitive for example acceleration..0.100. to Acceleration. I removed the two cars that did not have Fast Charge (the Renault Twingo Electric and the e.Go e.wave X) capability because this was an important feature in the linear regression and was impacting their price. Finally I made sure all the continuous variables were next to each other to simplify calling them. I split the dataframe into two. One with prices(307 objects) and one with missing prices (51 objects).

After cleaning the data 45 unique car makes were included in the ecars data used to create the linear model and 22 unique car makes were included in the data with missing prices. Additionally 14 makes that have 10 or more car models are highlighted throughout the project.

length(ecars$Price)
[1] 307
ecars
library(tibble)

ggplot(ecars, aes(Price, y = factor(0))) +
  geom_boxplot()+
  theme(axis.title.y=element_blank(),axis.text.y=element_blank(),axis.ticks.y=element_blank())

NA
NA
NA
Noecars = ecars

Noecars$Make2 = Noecars$Make
Noecars
makes = top_10$Make
makes
  [1] "Tesla"      "Tesla"      "MG"         "Tesla"      "Tesla"      "BMW"        "Volvo"      "Citroen"    "BMW"        "BMW"       
 [11] "Hyundai"    "Tesla"      "Tesla"      "BMW"        "Fiat"       "Tesla"      "BMW"        "BMW"        "Opel"       "MG"        
 [21] "BMW"        "Volvo"      "Volkswagen" "BMW"        "Audi"       "MG"         "Hyundai"    "Volkswagen" "Peugeot"    "Audi"      
 [31] "BMW"        "Hyundai"    "Hyundai"    "Volkswagen" "Volkswagen" "Citroen"    "MG"         "Hyundai"    "Tesla"      "Volvo"     
 [41] "BMW"        "Hyundai"    "Opel"       "MG"         "Mercedes"   "Volvo"      "BMW"        "Audi"       "MG"         "Hyundai"   
 [51] "Tesla"      "Mercedes"   "Hyundai"    "Peugeot"    "Tesla"      "Volvo"      "Hyundai"    "Volkswagen" "Audi"       "BMW"       
 [61] "Audi"       "BMW"        "Fiat"       "MG"         "Volkswagen" "Mercedes"   "Citroen"    "Volvo"      "Peugeot"    "MG"        
 [71] "MG"         "Audi"       "Volvo"      "Mercedes"   "Mercedes"   "NIO"        "Volkswagen" "NIO"        "Volvo"      "Mercedes"  
 [81] "Volvo"      "Mercedes"   "Peugeot"    "Mercedes"   "Opel"       "Volkswagen" "Citroen"    "Volvo"      "Volkswagen" "Mercedes"  
 [91] "Mercedes"   "Mercedes"   "Peugeot"    "Hyundai"    "Audi"       "NIO"        "Audi"       "BMW"        "Audi"       "Porsche"   
[101] "Porsche"    "BMW"        "Opel"       "Volvo"      "Volkswagen" "Fiat"       "Opel"       "Citroen"    "Mercedes"   "NIO"       
[111] "Citroen"    "Mercedes"   "MG"         "Mercedes"   "Mercedes"   "Porsche"    "Peugeot"    "NIO"        "NIO"        "Mercedes"  
[121] "Mercedes"   "Audi"       "Fiat"       "Audi"       "NIO"        "Mercedes"   "Mercedes"   "NIO"        "Mercedes"   "Audi"      
[131] "Porsche"    "Mercedes"   "Mercedes"   "Mercedes"   "Porsche"    "Mercedes"   "Porsche"    "Mercedes"   "Opel"       "Mercedes"  
[141] "Audi"       "Audi"       "Fiat"       "Mercedes"   "Porsche"    "Mercedes"   "Mercedes"   "Citroen"    "Mercedes"   "Opel"      
[151] "NIO"        "Opel"       "Citroen"    "Mercedes"   "Mercedes"   "Porsche"    "Peugeot"    "Peugeot"    "Peugeot"    "Porsche"   
[161] "Porsche"    "Mercedes"   "Mercedes"   "Mercedes"   "Citroen"    "NIO"        "Peugeot"    "Peugeot"    "Porsche"    "Porsche"   
[171] "Peugeot"    "Fiat"       "Citroen"    "Porsche"    "Citroen"    "Fiat"       "Porsche"    "Porsche"    "Citroen"    "Citroen"   
[181] "Opel"       "Citroen"    "Porsche"    "Opel"       "Porsche"    "Peugeot"    "Mercedes"   "Peugeot"    "Fiat"       "Porsche"   
[191] "Mercedes"   "Opel"       "Opel"       "Opel"       "Peugeot"    "Citroen"    "Fiat"       "Opel"       "Opel"       "Fiat"      
Noecars$Make3 = ifelse(Noecars$Make2 %in% makes, Noecars$Make2, "Other")
Noecars$Make2 %in% makes
  [1]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE
 [22] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE
 [43] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
 [64] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE
 [85] FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
[106]  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE
[127] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE
[148]  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
[169]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE
[190] FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE
[211]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
[232] FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
[253] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE
[274]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[295]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
Noecars
ecars_make

is_outlier <- function(x) {
  return(x < quantile(x, 0.25) - 1.5 * IQR(x) | x > quantile(x, 0.75) + 1.5 * IQR(x))
}

dat <- ecars %>% tibble::rownames_to_column(var="outlier") %>%
  mutate(is_outlier=ifelse(is_outlier(Price), Price, as.numeric(NA)))

dat
dat$outlier[which(is.na(dat$is_outlier))] <- as.numeric(NA)

ggplot(dat, aes(y=Price, x=factor(0))) + geom_boxplot() + geom_text(aes(label=outlier),na.rm=TRUE,nudge_y=0.1)

ggplot(ecars_make, aes(Top_speed, Make, fill = Make)) +
   scale_fill_manual(values = make_colors)+
  geom_boxplot(outlier.colour="black", outlier.shape=16, outlier.size=2, notch=FALSE)
ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_cost = (mean(Price)/1000)) %>%
  ggplot(., aes(x = Make, y = average_cost, fill = Make, label = Make)) +
  geom_bar(stat = 'identity') +
  scale_fill_manual(values = make_colors) +
  ylab('Average cost in Germany in 100s of eruros')+
  theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) +
  geom_text(angle = 90, position = position_stack(vjust = 0.5)) + 
  theme(legend.position = "none")
ecars
top_10 = ecars %>% group_by(Make) %>%
  filter(n() >= 10) #%>%
  #summarise(average_cost = mean(Price))
top_10



make_colors = c('#e6194b', '#f58231',  '#ffe119', 
                '#bcf60c','#3cb44b', '#008080',
                '#aaffc3', '#4363d8', '#000075',
                '#46f0f0', '#911eb4', '#e6beff',
                '#f032e6', '#fabebe')


ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  ggplot(., aes(x = Battery, y = Price)) +
  geom_point(aes(col = Make), size = 2) + 
  scale_color_manual(values = make_colors)



ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  ggplot(., aes(x = Efficiency, y = Price)) +
  geom_point(aes(col = Make)) 


efficiency_make = ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  ggplot(., aes(x = Efficiency, y = Price)) +
  geom_point(aes(col = Make), show.legend = FALSE) +
  facet_wrap(~Make)+
  scale_color_manual(values = make_colors)

efficiency_make


battery_make = ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  ggplot(., aes(x = Battery, y = Price)) +
  geom_point(aes(col = Make), show.legend = FALSE) +
  facet_wrap(~Make)
battery_make

#ggsave('battery_make.png', width = 15, height = 9)

#ggsave('efficiency_make.png', width = 15, height = 9)

#keep working on this'
battery_price = ggplot(NULL, aes(x = 'Battery', y = Price)) +
  geom_point(data = ecars, aes(x = Battery, y = Price)) +
  geom_point(data = top_10, aes(x = Battery, y = Price, col = Make))# + scale_color_manual(values = make_colors)#

battery_price
ggsave('battery_price.png', width = 10)
Saving 10 x 4.51 in image

#ecars %>% group_by(Make)%>%
 # summarise(average_cost = mean(Price)) %>%
  #arrange(average_cost)
ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  ggplot(., aes(x = Battery, y = Price)) +
  geom_point(aes(col = Make), show.legend = FALSE) 

BatvPrice = ggplot(NULL, aes(x = Battery, y = Price)) +
  geom_point(data = ecars, aes(x = Battery, y = Price, fill = 'black')) +
  geom_point(data = top_10, aes(x = Battery, y = Price, col = Make)) + 
  scale_color_manual(values = make_colors)+
  xlab("Battery Capacity (kWh)") + 
  ylab("Price in Germany (euros) ") +
  ggtitle('Electric Vehicle Battery vs. Price (makes with 10+ Models Highlighted)') +
  labs(fill="") +
  scale_fill_discrete(labels=c('Other')) +
  theme(legend.position = "bottom")

BatvPrice

ggsave('BatvPrice.png', width = 10)

ecars
ggarrange(a, b, c, d, 
          labels = c("A", "B", "C", "D"),
          ncol = 2, nrow = 2)
BatvRange = ggplot(NULL, aes(x = Battery, y = Range)) +
  geom_point(data = ecars, aes(x = Battery, y = Range, fill = 'black')) +
  geom_point(data = top_10, aes(x = Battery, y = Range, col = Make)) + 
  scale_color_manual(values = make_colors)+
  xlab("Battery Capacity (kWh)") + 
  ylab("Range (km on one charge) ") +
  ggtitle('Electric Vehicle Battery vs. Range (makes with 10+ Models Highlighted)') +
  labs(fill="") +
  scale_fill_discrete(labels=c('Other')) +
  theme(legend.position = "bottom")


AccvPrice = ggplot(NULL, aes(x = Acceleration, y = Price)) +
  geom_point(data = ecars, aes(x = Acceleration, y = Price, fill = 'black')) +
  geom_point(data = top_10, aes(x = Acceleration, y = Price, col = Make)) + 
  scale_color_manual(values = make_colors)+
  xlab("Acceleration (seconds to 100 km/hr)") + 
  ylab("Price in Germany (euros) ") +
  ggtitle('Acceleration vs. Price (makes with 10+ Models Highlighted)') +
  labs(fill="") +
  xlim(2,15)+
  scale_fill_discrete(labels=c('Other')) +
  theme(legend.position = "bottom")

BatvRange
BatvPrice
AccvPrice
unique(ecars$Make)
unique(ecars_missing_price$Make)

length(unique(ecars$Make))
length(unique(ecars_missing_price$Make))

ecars_missing_price
ecars
plot(ecars[,4:10], main = 'Comparison of all Quantitive Features')
plot(ecars$Acceleration, ecars$Battery)

ecars$Price_pow = (ecars$Price ** -.5)
ecars$Speed_pow = (ecars$Top_speed ** .25)
ecars$Efficiency_pow = (ecars$Efficiency ** .25)
summary(ecars)
sapply(ecars, sd)
hist(ecars$Price) 
hist(ecars$Price_pow) 
hist(ecars$Efficiency)
hist(ecars$Price_pow)
ecars

Colinearity with predicting Range based n battery

ecars %>% group_by(Make) %>%
  filter(n() >= 10) %>%o
  ggplot(., aes(x = Battery, y = Price)) +
  

RBmodel = lm(Range ~  Battery, data = ecars)
summary(RBmodel)
plot(RBmodel) 

PBmodel = lm(Price ~  Battery, data = ecars)
summary(PBmodel)
plot(PBmodel) 

ATmodel = lm(Top_speed ~ Acceleration, data = ecars)
summary(ATmodel)
plot(ATmodel)

model = lm(Price_pow ~ Efficiency_pow + Range + Speed_pow + Fast_charge, data = ecars)
summary(model) 
plot(model)

#battery speed_pow efficiency and fast charge 

With transformation done to price

ecars_missing_price$Speed_pow = (ecars_missing_price$Top_speed ** .25)
ecars_missing_price$Efficiency_pow = (ecars_missing_price$Efficiency ** .25)
test = predict(model, ecars_missing_price, interval = 'prediction')
test_2_dollars = (1/(test))^2
ecars_missing_price
test_2_dollars
ecars_missing_price$predicted_price = (test_2_dollars[,1])
ecars_missing_price
test2 = predict(model, ecars, interval = 'prediction')
test3 = predict(model, ecars, interval = 'confidence')
test2_2_dollars = (1/(test2))^2
test3_2_dollars = (1/(test3))^2
test2_2_dollars
test3_2_dollars
test2_2_dollarsnew = data.frame(Name = ecars$Car_name,
                 Make = ecars$Make,
                 Price = ecars$Price/1000, 
                 Predicted_price = (test2_2_dollars[,1]/1000),
                 Predicted_price_lwr = (test2_2_dollars[,2]/1000),
                 Predicted_price_upr = (test2_2_dollars[,3]/1000),
                 Confidence_price_lwr = (test3_2_dollars[,2]/1000),
                 Confidence_price_upr = (test3_2_dollars[,3])/1000)
test2_2_dollarsnew
# cars groups by brands with the most models

most_makes = test2_2_dollarsnew %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_cost = (mean(Price)), average_predicted_cost = (mean(Predicted_price)))



gplt1 = ggplot(NULL, aes(Predicted_price, Price)) +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price)) +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price_lwr), col = 'red') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price_upr), col = 'red') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Confidence_price_lwr), col = 'blue') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Confidence_price_upr), col = 'blue') +
      ylim(0,250)+ 
geom_point(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Price), alpha = .5) +
geom_point(data = most_makes, aes(x = average_predicted_cost, y = average_cost), size = 3, shape = 23, fill = make_colors) +
 scale_color_manual(values = make_colors)

gplt1

ggsave('gplt1.png', width = 15)
         
gplt1 = ggplot(NULL, aes(Predicted_price, Price)) +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price)) +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price_lwr), col = 'red') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Predicted_price_upr), col = 'red') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Confidence_price_lwr), col = 'blue') +
      geom_line(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Confidence_price_upr), col = 'blue') +
      ylim(0,250)+ 
      geom_point(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Price), alpha = .5) +
      geom_point(data = most_makes, aes(x = average_predicted_cost, y = average_cost), size = 3, shape = 23, fill = make_colors) +
      scale_color_manual(values = make_colors)
test2_2_dollarsnew %>%
  arrange(Predicted_price)
plot_ly(
  data = ecars_make,
  x = ~Price,
  type = "box",
  text = ~Car_name,
  name = '',
  tooltip = c("x", "text"))%>% 
  layout(title = "Box Plot of Selected Feature",
         yaxis = list(title = ''),
         xaxis = list(title = ''))
Warning: 'box' objects don't have these attributes: 'tooltip'
Valid attributes include:
'alignmentgroup', 'boxmean', 'boxpoints', 'customdata', 'customdatasrc', 'dx', 'dy', 'fillcolor', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertemplate', 'hovertemplatesrc', 'hovertext', 'hovertextsrc', 'ids', 'idssrc', 'jitter', 'legendgroup', 'legendgrouptitle', 'legendrank', 'line', 'lowerfence', 'lowerfencesrc', 'marker', 'mean', 'meansrc', 'median', 'mediansrc', 'meta', 'metasrc', 'name', 'notched', 'notchspan', 'notchspansrc', 'notchwidth', 'offsetgroup', 'opacity', 'orientation', 'pointpos', 'q1', 'q1src', 'q3', 'q3src', 'quartilemethod', 'sd', 'sdsrc', 'selected', 'selectedpoints', 'showlegend', 'stream', 'text', 'textsrc', 'transforms', 'type', 'uid', 'uirevision', 'unselected', 'upperfence', 'upperfencesrc', 'visible', 'whiskerwidth', 'width', 'x', 'x0', 'xaxis', 'xcalendar', 'xhoverformat', 'xperiod', 'xperiod0', 'xperiodalignment', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'yhoverformat', 'yperiod', 'yperiod0', 'yperiodalignment', 'ysrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
Warning: 'box' objects don't have these attributes: 'tooltip'
Valid attributes include:
'alignmentgroup', 'boxmean', 'boxpoints', 'customdata', 'customdatasrc', 'dx', 'dy', 'fillcolor', 'hoverinfo', 'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertemplate', 'hovertemplatesrc', 'hovertext', 'hovertextsrc', 'ids', 'idssrc', 'jitter', 'legendgroup', 'legendgrouptitle', 'legendrank', 'line', 'lowerfence', 'lowerfencesrc', 'marker', 'mean', 'meansrc', 'median', 'mediansrc', 'meta', 'metasrc', 'name', 'notched', 'notchspan', 'notchspansrc', 'notchwidth', 'offsetgroup', 'opacity', 'orientation', 'pointpos', 'q1', 'q1src', 'q3', 'q3src', 'quartilemethod', 'sd', 'sdsrc', 'selected', 'selectedpoints', 'showlegend', 'stream', 'text', 'textsrc', 'transforms', 'type', 'uid', 'uirevision', 'unselected', 'upperfence', 'upperfencesrc', 'visible', 'whiskerwidth', 'width', 'x', 'x0', 'xaxis', 'xcalendar', 'xhoverformat', 'xperiod', 'xperiod0', 'xperiodalignment', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'yhoverformat', 'yperiod', 'yperiod0', 'yperiodalignment', 'ysrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
ecars[,5]
  [1] 172 137 183 171 149 164 197 173 176 170 157 158 170 164 181 168 170 192 159 180 165 178 166 152 171 179 167 185 199 188 175 185
 [33] 180 162 208 210 169 165 169 168 166 165 226 162 210 171 240 161 156 168 206 149 164 193 166 223 177 186 160 172 175 190 164 185
 [65] 176 220 168 178 166 148 178 193 197 200 171 201 195 177 159 191 202 185 171 176 230 160 199 168 213 200 200 170 192 169 209 203
 [97] 183 169 202 170 183 183 217 167 175 192 174 176 156 169 224 231 158 171 162 190 168 191 165 169 175 218 200 185 203 209 188 177
[129] 177 230 164 290 176 204 182 237 180 175 198 197 211 158 191 188 223 169 201 170 168 240 188 169 217 176 153 193 181 154 184 154
[161] 159 238 183 187 164 164 184 205 155 190 167 195 178 177 173 196 233 186 173 208 169 186 156 179 158 157 228 226 290 215 205 154
[193] 169 178 174 202 176 195 232 209 214 178 188 186 176 193 200 174 173 200 159 195 178 211 193 203 183 208 186 177 188 168 169 221
[225] 200 184 174 179 190 208 221 215 257 180 201 221 186 194 220 162 218 257 226 171 206 195 187 250 168 221 262 171 262 201 226 257
[257] 195 295 188 257 226 262 195 190 206 187 286 290 286 168 203 257 207 257 250 197 197 262 262 257 204 226 158 188 212 262 250 250
[289] 262 195 232 192 250 293 250 257 207 286 262 250 257 250 257 250 257 257 257
options(repr.plot.width = 15, repr.plot.height =2) 

ggplot(data = test2_2_dollarsnew, aes(x = Predicted_price, y = Price)) +
  geom_point() +
  geom_line(aes(x = Predicted_price, y = Predicted_price)) +
  geom_line(aes(x = Predicted_price, y = Predicted_price_lwr), col = 'red') +
  geom_line(aes(x = Predicted_price, y = Predicted_price_upr)) +
  geom_line(aes(x = Predicted_price, y = Confidence_price_lwr)) +
  geom_line(aes(x = Predicted_price, y = Confidence_price_upr)) #+
 geom_point(aes(x = most_makes$average_cost, y =most_makes$average_predicted_cost))


  
new
new
new %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_cost = (mean(Price)/1000), average_predicted_cost = (mean(Predicted_price)/1000)) #%>%
  #ggplot(., aes(x = Make, y = average_predicted_cost)) +
  #geom_col(aes(fill = Make)) + 
  #ylab('Average cost in Germany in thousands of Eruros')+
  #theme(axis.title.x=element_blank(),
   #     axis.text.x=element_blank(),
    #    axis.ticks.x=element_blank())
new %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_price = (mean(Price)/1000), average_predicted_price =  (mean(Predicted_price)/1000))%>%
  ggplot(., aes(x = average_predicted_price, y = average_price)) +
  geom_point(aes(color = Make), size =4) 
  
new
new %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_price = (mean(Price)/1000), average_predicted_price = (mean(Predicted_price)/1000))%>%
  ggplot(., aes(x = average_predicted_price, y = average_price)) +
  geom_point(aes(color = Make), size =4) +
  geom_line(aes(x = average_predicted_price, y = average_predicted_price)) + 
predict(model, newdata, interval = 'confidence')
predict(model, newdata, interval = 'prediction')
new
new %>% group_by(Make) %>%
  filter(n() >= 10) %>%
  summarise(average_price = (mean(Price)/1000), average_predicted_price = (mean(Predicted_price)/1000))
ecars_missing_price
pre
model
ecars
model.empty = lm(Price_pow ~ 1, data = ecars)
model.full = lm(Price_pow ~ Efficiency_pow + Range + Battery + Speed_pow + Fast_charge + Acceleration, data = ecars)
scope = list(lower = formula(model.empty), upper = formula(model.full))
scope
forwardAIC = step(model.empty, scope, direction = 'forward', k = 2)

battery speed_pow efficiency and fast charge

model.empty2 = lm(Price ~ 1, data = ecars)
model.full2 = lm(Price ~ Efficiency + Range + Battery + Top_speed + Fast_charge + Acceleration, data = ecars)
scope2 = list(lower = formula(model.empty2), upper = formula(model.full2))
scope2
forwardAIC2 = step(model.empty2, scope2, direction = 'forward', k = 2)
model.empty3 = lm(Price_pow ~ 1, data = ecars)
model.full3 = lm(Price_pow ~ Efficiency + Range + Battery + Top_speed + Fast_charge + Acceleration, data = ecars)
scope3 = list(lower = formula(model.empty3), upper = formula(model.full3))
forwardAIC3 = step(model.empty3, scope3, direction = 'forward', k = 2)

I’m getting a lower AIC when I run these without transforming them??? I need to transform price but not the others?? not sure what to do??

model.empty = lm(Price_pow ~ 1, data = ecars)
model.full = lm(Price_pow ~ Efficiency_pow + Range + Battery + Speed_pow + Fast_charge + Acceleration, data = ecars)
scope = list(lower = formula(model.empty), upper = formula(model.full))
scope
forwardAIC = step(model.empty, scope, direction = 'forward', k = 2)
broom::glance(model)
broom::glance(model.full)
model_best = lm(Price_pow ~ Efficiency_pow + Range + Battery + Speed_pow + Fast_charge, data = ecars)
broom::glance(model.full3)
broom::glance(model_best)
ecars
model_box = lm(Price ~ Top_speed + Range + Efficiency + Fast_charge + Acceleration, data = ecars)
summary(model_box)
bc = boxCox(model_box)

lambda = bc$x[which(bc$y == max(bc$y))]
lambda
Price.bc = (ecars$Price^lambda - 1)/lambda
Price.bc
model.bc = lm(Price.bc ~ Top_speed + Range + Efficiency + Fast_charge + Acceleration, data = ecars)
              
summary(model.bc)
broom::glance(model.bc)

hist(Price.bc)

****This is how to undo the lambda transformation

((Price.bc*lambda) + 1)^(1/lambda)
ecars$Price
plot.new()
plot( x = 50, y = 54)
lines(predicted_price$Predicted, predicted_price$Predicted)
ecars_missing_price

This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KQWJvdXQgdGhpcyBmaWxlDQpEYXRhIEZpZWxkczoNCg0KLSBCYXR0ZXJ5OiBUaGUgY2FwYWNpdHkgb2YgdGhlIHZlaGljbGUncyBiYXR0ZXJ5IGluIGtpbG93YXR0LWhvdXJzIChrV2gpLg0KDQotIENhcl9uYW1lOiBUaGUgbW9kZWwgbmFtZSBvZiB0aGUgZWxlY3RyaWMgdmVoaWNsZS4NCg0KLSBDYXJfbmFtZV9saW5rOiBBIGRpcmVjdCBsaW5rIHRvIHRoZSBjb3JyZXNwb25kaW5nIHBhZ2Ugb24gRVYgRGF0YWJhc2UgZm9yIG1vcmUgaW4tZGVwdGggaW5mb3JtYXRpb24uDQoNCi0gRWZmaWNpZW5jeTogVGhlIGVuZXJneSBlZmZpY2llbmN5IHJhdGluZyBvZiB0aGUgdmVoaWNsZSBpbiB3YXR0LWhvdXJzIHBlciBraWxvbWV0ZXIgKFdoL2ttKS4NCg0KLSBGYXN0X2NoYXJnZTogVGhlIGZhc3QtY2hhcmdpbmcgY2FwYWJpbGl0eSBvZiB0aGUgdmVoaWNsZSBpbiBtaW51dGVzIGZvciBhIGNlcnRhaW4gY2hhcmdpbmcgcGVyY2VudGFnZS4NCg0KLSBQcmljZS5ERS46VGhlIHByaWNlIG9mIHRoZSBlbGVjdHJpYyB2ZWhpY2xlIGluIEdlcm1hbnkuDQoNCi0gUmFuZ2U6IFRoZSBkcml2aW5nIHJhbmdlIG9mIHRoZSB2ZWhpY2xlIG9uIGEgc2luZ2xlIGNoYXJnZSBpbiBraWxvbWV0ZXJzLg0KDQotIFRvcF9zcGVlZDpUaGUgbWF4aW11bSBzcGVlZCB0aGUgdmVoaWNsZSBjYW4gYWNoaWV2ZSBpbiBraWxvbWV0ZXJzIHBlciBob3VyLg0KDQotIEFjY2VsZXJhdGlvbi4uMC4xMDAuOiBUaGUgYWNjZWxlcmF0aW9uIHRpbWUgZnJvbSAwIHRvIDEwMCBraWxvbWV0ZXJzIHBlciBob3VyLg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShNQVNTKQ0KbGlicmFyeShyZXByKQ0KDQpsaWJyYXJ5KHBhbHMpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KZWNhcnNfcmF3ID0gcmVhZC5jc3YoJ0VWX2NhcnMuY3N2JykNCmVjYXJzX3Jhdw0KDQpgYGANCg0KYGBge3J9DQojcmVuYW1lIHNvbWUgb2YgdGhlIGNvbHVtbnMNCmVjYXJzX3JhdyA9IGVjYXJzX3JhdyAlPiUgcmVuYW1lKFByaWNlID0gUHJpY2UuREUuLCBBY2NlbGVyYXRpb24gPSBhY2NlbGVyYXRpb24uLjAuMTAwLikNCmBgYA0KDQpgYGB7cn0NCg0KIyBleHRyYWN0IHRoZSBNYWtlIG9mIGVhY2ggY2FyIGludG8gaXRzIG93biBjb2x1bW4NCm1ha2UgPSBzdHJzcGxpdChlY2Fyc19yYXckQ2FyX25hbWUsIHNwbGl0ID0gJyAnKQ0KDQptYWtlXyA9IGMoKQ0KbiA9IGxlbmd0aChtYWtlKQ0KDQpmb3IgKGkgaW4gMTpuKSB7DQogIG1ha2VfW2ldID0gbWFrZVtbaV1dWzFdDQp9DQoNCmVjYXJzX3JhdyRNYWtlID0gbWFrZV8NCmBgYA0KDQpgYGB7cn0NCiMgbW92ZSBjb2x1bW5zIHNvIGNvbnRpbnVvdXMgdmFyaWFibGVzIGFyZSB0b2dldGhlciANCmVjYXJzX3JhdyA9IGVjYXJzX3JhdyAlPiUgcmVsb2NhdGUoTWFrZSwgLmJlZm9yZSA9IENhcl9uYW1lX2xpbmspDQplY2Fyc19yYXcgPSBlY2Fyc19yYXcgJT4lIHJlbG9jYXRlKEJhdHRlcnksIC5hZnRlciA9IENhcl9uYW1lX2xpbmspDQplY2Fyc19yYXcNCmBgYA0KYGBge3J9DQplY2Fyc19yYXcgPSBlY2Fyc19yYXcgJT4lIGZpbHRlcighaXMubmEoRmFzdF9jaGFyZ2UpKQ0KZWNhcnMgPSBlY2Fyc19yYXcgJT4lIGZpbHRlcighaXMubmEoUHJpY2UpKQ0KZWNhcnNfbWlzc2luZ19wcmljZSA9IGVjYXJzX3JhdyAlPiUgZmlsdGVyKGlzLm5hKFByaWNlKSkNCmBgYA0KDQpUaGlzIGRhdGEgcmVxdWlyZWQgbWluaW1hbCBwcm9jZXNzaW5nLiBJIGNyZWF0ZWQgYSBNYWtlIHZhcmlhYmxlIGJ5IGV4dHJhY3RpbmcgdGhlIGZpcnN0IHdvcmQgZnJvbSB0aGUgQ2FyX25hbWUgdmFyaWFibGUuIEkgYWxzbyByZW5hbWVkIHNldmVyYWwgY29sdW1ucyB0byBtYWtlIHRoZW0gbW9yZSBpbnR1aXRpdmUgZm9yIGV4YW1wbGUgYWNjZWxlcmF0aW9uLi4wLjEwMC4gdG8gQWNjZWxlcmF0aW9uLiBJIHJlbW92ZWQgdGhlIHR3byBjYXJzIHRoYXQgZGlkIG5vdCBoYXZlIEZhc3QgQ2hhcmdlICh0aGUgUmVuYXVsdCBUd2luZ28gRWxlY3RyaWMgYW5kIHRoZSBlLkdvIGUud2F2ZSBYKSBjYXBhYmlsaXR5IGJlY2F1c2UgdGhpcyB3YXMgYW4gaW1wb3J0YW50IGZlYXR1cmUgaW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIGFuZCB3YXMgaW1wYWN0aW5nIHRoZWlyIHByaWNlLiBGaW5hbGx5IEkgbWFkZSBzdXJlIGFsbCB0aGUgY29udGludW91cyB2YXJpYWJsZXMgd2VyZSBuZXh0IHRvIGVhY2ggb3RoZXIgdG8gc2ltcGxpZnkgY2FsbGluZyB0aGVtLiBJIHNwbGl0IHRoZSBkYXRhZnJhbWUgaW50byB0d28uIE9uZSB3aXRoIHByaWNlcygzMDcgb2JqZWN0cykgYW5kIG9uZSB3aXRoIG1pc3NpbmcgcHJpY2VzICg1MSBvYmplY3RzKS4gDQoNCkFmdGVyIGNsZWFuaW5nIHRoZSBkYXRhIDQ1IHVuaXF1ZSBjYXIgbWFrZXMgd2VyZSBpbmNsdWRlZCBpbiB0aGUgZWNhcnMgZGF0YSB1c2VkIHRvIGNyZWF0ZSB0aGUgbGluZWFyIG1vZGVsIGFuZCAyMiB1bmlxdWUgY2FyIG1ha2VzIHdlcmUgaW5jbHVkZWQgaW4gdGhlIGRhdGEgd2l0aCBtaXNzaW5nIHByaWNlcy4gQWRkaXRpb25hbGx5IDE0IG1ha2VzIHRoYXQgaGF2ZSAxMCBvciBtb3JlIGNhciBtb2RlbHMgYXJlIGhpZ2hsaWdodGVkIHRocm91Z2hvdXQgdGhlIHByb2plY3QuICANCg0KYGBge3J9DQpsZW5ndGgoZWNhcnMkUHJpY2UpDQpgYGANCmBgYHtyfQ0KZWNhcnMNCmxpYnJhcnkodGliYmxlKQ0KDQpnZ3Bsb3QoZWNhcnMsIGFlcyhQcmljZSwgeSA9IGZhY3RvcigwKSkpICsNCiAgZ2VvbV9ib3hwbG90KCkrDQogIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpDQoNCg0KDQpgYGANCmBgYHtyfQ0KTm9lY2FycyA9IGVjYXJzDQoNCk5vZWNhcnMkTWFrZTIgPSBOb2VjYXJzJE1ha2UNCk5vZWNhcnMNCm1ha2VzID0gdG9wXzEwJE1ha2UNCm1ha2VzDQpOb2VjYXJzJE1ha2UzID0gaWZlbHNlKE5vZWNhcnMkTWFrZTIgJWluJSBtYWtlcywgTm9lY2FycyRNYWtlMiwgIk90aGVyIikNCk5vZWNhcnMkTWFrZTIgJWluJSBtYWtlcw0KTm9lY2Fycw0KYGBgDQoNCmBgYHtyfQ0KZWNhcnNfbWFrZQ0KDQppc19vdXRsaWVyIDwtIGZ1bmN0aW9uKHgpIHsNCiAgcmV0dXJuKHggPCBxdWFudGlsZSh4LCAwLjI1KSAtIDEuNSAqIElRUih4KSB8IHggPiBxdWFudGlsZSh4LCAwLjc1KSArIDEuNSAqIElRUih4KSkNCn0NCg0KZGF0IDwtIGVjYXJzICU+JSB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbih2YXI9Im91dGxpZXIiKSAlPiUNCiAgbXV0YXRlKGlzX291dGxpZXI9aWZlbHNlKGlzX291dGxpZXIoUHJpY2UpLCBQcmljZSwgYXMubnVtZXJpYyhOQSkpKQ0KDQpkYXQNCmRhdCRvdXRsaWVyW3doaWNoKGlzLm5hKGRhdCRpc19vdXRsaWVyKSldIDwtIGFzLm51bWVyaWMoTkEpDQoNCmdncGxvdChkYXQsIGFlcyh5PVByaWNlLCB4PWZhY3RvcigwKSkpICsgZ2VvbV9ib3hwbG90KCkgKyBnZW9tX3RleHQoYWVzKGxhYmVsPW91dGxpZXIpLG5hLnJtPVRSVUUsbnVkZ2VfeT0wLjEpDQoNCmdncGxvdChlY2Fyc19tYWtlLCBhZXMoVG9wX3NwZWVkLCBNYWtlLCBmaWxsID0gTWFrZSkpICsNCiAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKSsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJibGFjayIsIG91dGxpZXIuc2hhcGU9MTYsIG91dGxpZXIuc2l6ZT0yLCBub3RjaD1GQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmVjYXJzICU+JSBncm91cF9ieShNYWtlKSAlPiUNCiAgZmlsdGVyKG4oKSA+PSAxMCkgJT4lDQogIHN1bW1hcmlzZShhdmVyYWdlX2Nvc3QgPSAobWVhbihQcmljZSkvMTAwMCkpICU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBNYWtlLCB5ID0gYXZlcmFnZV9jb3N0LCBmaWxsID0gTWFrZSwgbGFiZWwgPSBNYWtlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtYWtlX2NvbG9ycykgKw0KICB5bGFiKCdBdmVyYWdlIGNvc3QgaW4gR2VybWFueSBpbiAxMDBzIG9mIGVydXJvcycpKw0KICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsNCiAgZ2VvbV90ZXh0KGFuZ2xlID0gOTAsIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCmBgYHtyfQ0KZWNhcnMNCmBgYA0KDQpgYGB7cn0NCnRvcF8xMCA9IGVjYXJzICU+JSBncm91cF9ieShNYWtlKSAlPiUNCiAgZmlsdGVyKG4oKSA+PSAxMCkgIyU+JQ0KICAjc3VtbWFyaXNlKGF2ZXJhZ2VfY29zdCA9IG1lYW4oUHJpY2UpKQ0KdG9wXzEwDQoNCg0KDQptYWtlX2NvbG9ycyA9IGMoJyNlNjE5NGInLCAnI2Y1ODIzMScsICAnI2ZmZTExOScsIA0KICAgICAgICAgICAgICAgICcjYmNmNjBjJywnIzNjYjQ0YicsICcjMDA4MDgwJywNCiAgICAgICAgICAgICAgICAnI2FhZmZjMycsICcjNDM2M2Q4JywgJyMwMDAwNzUnLA0KICAgICAgICAgICAgICAgICcjNDZmMGYwJywgJyM5MTFlYjQnLCAnI2U2YmVmZicsDQogICAgICAgICAgICAgICAgJyNmMDMyZTYnLCAnI2ZhYmViZScpDQoNCg0KZWNhcnMgJT4lIGdyb3VwX2J5KE1ha2UpICU+JQ0KICBmaWx0ZXIobigpID49IDEwKSAlPiUNCiAgZ2dwbG90KC4sIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2wgPSBNYWtlKSwgc2l6ZSA9IDIpICsgDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtYWtlX2NvbG9ycykNCg0KDQplY2FycyAlPiUgZ3JvdXBfYnkoTWFrZSkgJT4lDQogIGZpbHRlcihuKCkgPj0gMTApICU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBFZmZpY2llbmN5LCB5ID0gUHJpY2UpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbCA9IE1ha2UpKSANCg0KZWZmaWNpZW5jeV9tYWtlID0gZWNhcnMgJT4lIGdyb3VwX2J5KE1ha2UpICU+JQ0KICBmaWx0ZXIobigpID49IDEwKSAlPiUNCiAgZ2dwbG90KC4sIGFlcyh4ID0gRWZmaWNpZW5jeSwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2wgPSBNYWtlKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH5NYWtlKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKQ0KDQplZmZpY2llbmN5X21ha2UNCg0KYmF0dGVyeV9tYWtlID0gZWNhcnMgJT4lIGdyb3VwX2J5KE1ha2UpICU+JQ0KICBmaWx0ZXIobigpID49IDEwKSAlPiUNCiAgZ2dwbG90KC4sIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2wgPSBNYWtlKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH5NYWtlKQ0KYmF0dGVyeV9tYWtlDQojZ2dzYXZlKCdiYXR0ZXJ5X21ha2UucG5nJywgd2lkdGggPSAxNSwgaGVpZ2h0ID0gOSkNCg0KI2dnc2F2ZSgnZWZmaWNpZW5jeV9tYWtlLnBuZycsIHdpZHRoID0gMTUsIGhlaWdodCA9IDkpDQoNCiNrZWVwIHdvcmtpbmcgb24gdGhpcycNCmJhdHRlcnlfcHJpY2UgPSBnZ3Bsb3QoTlVMTCwgYWVzKHggPSAnQmF0dGVyeScsIHkgPSBQcmljZSkpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZWNhcnMsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSB0b3BfMTAsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlLCBjb2wgPSBNYWtlKSkjICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKSMNCg0KYmF0dGVyeV9wcmljZQ0KZ2dzYXZlKCdiYXR0ZXJ5X3ByaWNlLnBuZycsIHdpZHRoID0gMTApDQoNCiNlY2FycyAlPiUgZ3JvdXBfYnkoTWFrZSklPiUNCiAjIHN1bW1hcmlzZShhdmVyYWdlX2Nvc3QgPSBtZWFuKFByaWNlKSkgJT4lDQogICNhcnJhbmdlKGF2ZXJhZ2VfY29zdCkNCmBgYA0KYGBge3J9DQplY2FycyAlPiUgZ3JvdXBfYnkoTWFrZSkgJT4lDQogIGZpbHRlcihuKCkgPj0gMTApICU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBCYXR0ZXJ5LCB5ID0gUHJpY2UpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbCA9IE1ha2UpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSANCg0KQmF0dlByaWNlID0gZ2dwbG90KE5VTEwsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBlY2FycywgYWVzKHggPSBCYXR0ZXJ5LCB5ID0gUHJpY2UsIGZpbGwgPSAnYmxhY2snKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSB0b3BfMTAsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFByaWNlLCBjb2wgPSBNYWtlKSkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKSsNCiAgeGxhYigiQmF0dGVyeSBDYXBhY2l0eSAoa1doKSIpICsgDQogIHlsYWIoIlByaWNlIGluIEdlcm1hbnkgKGV1cm9zKSAiKSArDQogIGdndGl0bGUoJ0VsZWN0cmljIFZlaGljbGUgQmF0dGVyeSB2cy4gUHJpY2UgKG1ha2VzIHdpdGggMTArIE1vZGVscyBIaWdobGlnaHRlZCknKSArDQogIGxhYnMoZmlsbD0iIikgKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscz1jKCdPdGhlcicpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KDQpCYXR2UHJpY2UNCg0KZ2dzYXZlKCdCYXR2UHJpY2UucG5nJywgd2lkdGggPSAxMCkNCg0KZWNhcnMNCmBgYA0KYGBge3J9DQpnZ2FycmFuZ2UoYSwgYiwgYywgZCwgDQogICAgICAgICAgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiLCAiRCIpLA0KICAgICAgICAgIG5jb2wgPSAyLCBucm93ID0gMikNCmBgYA0KDQoNCmBgYHtyfQ0KQmF0dlJhbmdlID0gZ2dwbG90KE5VTEwsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFJhbmdlKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBlY2FycywgYWVzKHggPSBCYXR0ZXJ5LCB5ID0gUmFuZ2UsIGZpbGwgPSAnYmxhY2snKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSB0b3BfMTAsIGFlcyh4ID0gQmF0dGVyeSwgeSA9IFJhbmdlLCBjb2wgPSBNYWtlKSkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKSsNCiAgeGxhYigiQmF0dGVyeSBDYXBhY2l0eSAoa1doKSIpICsgDQogIHlsYWIoIlJhbmdlIChrbSBvbiBvbmUgY2hhcmdlKSAiKSArDQogIGdndGl0bGUoJ0VsZWN0cmljIFZlaGljbGUgQmF0dGVyeSB2cy4gUmFuZ2UgKG1ha2VzIHdpdGggMTArIE1vZGVscyBIaWdobGlnaHRlZCknKSArDQogIGxhYnMoZmlsbD0iIikgKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscz1jKCdPdGhlcicpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KDQoNCkFjY3ZQcmljZSA9IGdncGxvdChOVUxMLCBhZXMoeCA9IEFjY2VsZXJhdGlvbiwgeSA9IFByaWNlKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBlY2FycywgYWVzKHggPSBBY2NlbGVyYXRpb24sIHkgPSBQcmljZSwgZmlsbCA9ICdibGFjaycpKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IHRvcF8xMCwgYWVzKHggPSBBY2NlbGVyYXRpb24sIHkgPSBQcmljZSwgY29sID0gTWFrZSkpICsgDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtYWtlX2NvbG9ycykrDQogIHhsYWIoIkFjY2VsZXJhdGlvbiAoc2Vjb25kcyB0byAxMDAga20vaHIpIikgKyANCiAgeWxhYigiUHJpY2UgaW4gR2VybWFueSAoZXVyb3MpICIpICsNCiAgZ2d0aXRsZSgnQWNjZWxlcmF0aW9uIHZzLiBQcmljZSAobWFrZXMgd2l0aCAxMCsgTW9kZWxzIEhpZ2hsaWdodGVkKScpICsNCiAgbGFicyhmaWxsPSIiKSArDQogIHhsaW0oMiwxNSkrDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobGFiZWxzPWMoJ090aGVyJykpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCkJhdHZSYW5nZQ0KQmF0dlByaWNlDQpBY2N2UHJpY2UNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCnVuaXF1ZShlY2FycyRNYWtlKQ0KdW5pcXVlKGVjYXJzX21pc3NpbmdfcHJpY2UkTWFrZSkNCg0KbGVuZ3RoKHVuaXF1ZShlY2FycyRNYWtlKSkNCmxlbmd0aCh1bmlxdWUoZWNhcnNfbWlzc2luZ19wcmljZSRNYWtlKSkNCg0KZWNhcnNfbWlzc2luZ19wcmljZQ0KYGBgDQoNCmBgYHtyfQ0KZWNhcnMNCnBsb3QoZWNhcnNbLDQ6MTBdLCBtYWluID0gJ0NvbXBhcmlzb24gb2YgYWxsIFF1YW50aXRpdmUgRmVhdHVyZXMnKQ0KcGxvdChlY2FycyRBY2NlbGVyYXRpb24sIGVjYXJzJEJhdHRlcnkpDQoNCmVjYXJzJFByaWNlX3BvdyA9IChlY2FycyRQcmljZSAqKiAtLjUpDQplY2FycyRTcGVlZF9wb3cgPSAoZWNhcnMkVG9wX3NwZWVkICoqIC4yNSkNCmVjYXJzJEVmZmljaWVuY3lfcG93ID0gKGVjYXJzJEVmZmljaWVuY3kgKiogLjI1KQ0Kc3VtbWFyeShlY2FycykNCnNhcHBseShlY2Fycywgc2QpDQpoaXN0KGVjYXJzJFByaWNlKSANCmhpc3QoZWNhcnMkUHJpY2VfcG93KSANCmhpc3QoZWNhcnMkRWZmaWNpZW5jeSkNCmhpc3QoZWNhcnMkUHJpY2VfcG93KQ0KZWNhcnMNCmBgYA0KQ29saW5lYXJpdHkgd2l0aCBwcmVkaWN0aW5nIFJhbmdlIGJhc2VkIG4gYmF0dGVyeQ0KDQpgYGB7cn0NCmVjYXJzICU+JSBncm91cF9ieShNYWtlKSAlPiUNCiAgZmlsdGVyKG4oKSA+PSAxMCkgJT4lbw0KICBnZ3Bsb3QoLiwgYWVzKHggPSBCYXR0ZXJ5LCB5ID0gUHJpY2UpKSArDQogIA0KYGBgDQoNCmBgYHtyfQ0KDQpSQm1vZGVsID0gbG0oUmFuZ2UgfiAgQmF0dGVyeSwgZGF0YSA9IGVjYXJzKQ0Kc3VtbWFyeShSQm1vZGVsKQ0KcGxvdChSQm1vZGVsKSANCg0KUEJtb2RlbCA9IGxtKFByaWNlIH4gIEJhdHRlcnksIGRhdGEgPSBlY2FycykNCnN1bW1hcnkoUEJtb2RlbCkNCnBsb3QoUEJtb2RlbCkgDQoNCkFUbW9kZWwgPSBsbShUb3Bfc3BlZWQgfiBBY2NlbGVyYXRpb24sIGRhdGEgPSBlY2FycykNCnN1bW1hcnkoQVRtb2RlbCkNCnBsb3QoQVRtb2RlbCkNCg0KbW9kZWwgPSBsbShQcmljZV9wb3cgfiBFZmZpY2llbmN5X3BvdyArIFJhbmdlICsgU3BlZWRfcG93ICsgRmFzdF9jaGFyZ2UsIGRhdGEgPSBlY2FycykNCnN1bW1hcnkobW9kZWwpIA0KcGxvdChtb2RlbCkNCg0KI2JhdHRlcnkgc3BlZWRfcG93IGVmZmljaWVuY3kgYW5kIGZhc3QgY2hhcmdlIA0KDQpgYGANCldpdGggdHJhbnNmb3JtYXRpb24gZG9uZSB0byBwcmljZSANCmBgYHtyfQ0KZWNhcnNfbWlzc2luZ19wcmljZSRTcGVlZF9wb3cgPSAoZWNhcnNfbWlzc2luZ19wcmljZSRUb3Bfc3BlZWQgKiogLjI1KQ0KZWNhcnNfbWlzc2luZ19wcmljZSRFZmZpY2llbmN5X3BvdyA9IChlY2Fyc19taXNzaW5nX3ByaWNlJEVmZmljaWVuY3kgKiogLjI1KQ0KdGVzdCA9IHByZWRpY3QobW9kZWwsIGVjYXJzX21pc3NpbmdfcHJpY2UsIGludGVydmFsID0gJ3ByZWRpY3Rpb24nKQ0KdGVzdF8yX2RvbGxhcnMgPSAoMS8odGVzdCkpXjINCmVjYXJzX21pc3NpbmdfcHJpY2UNCnRlc3RfMl9kb2xsYXJzDQplY2Fyc19taXNzaW5nX3ByaWNlJHByZWRpY3RlZF9wcmljZSA9ICh0ZXN0XzJfZG9sbGFyc1ssMV0pDQplY2Fyc19taXNzaW5nX3ByaWNlDQpgYGANCmBgYHtyfQ0KdGVzdDIgPSBwcmVkaWN0KG1vZGVsLCBlY2FycywgaW50ZXJ2YWwgPSAncHJlZGljdGlvbicpDQp0ZXN0MyA9IHByZWRpY3QobW9kZWwsIGVjYXJzLCBpbnRlcnZhbCA9ICdjb25maWRlbmNlJykNCnRlc3QyXzJfZG9sbGFycyA9ICgxLyh0ZXN0MikpXjINCnRlc3QzXzJfZG9sbGFycyA9ICgxLyh0ZXN0MykpXjINCnRlc3QyXzJfZG9sbGFycw0KdGVzdDNfMl9kb2xsYXJzDQp0ZXN0Ml8yX2RvbGxhcnNuZXcgPSBkYXRhLmZyYW1lKE5hbWUgPSBlY2FycyRDYXJfbmFtZSwNCiAgICAgICAgICAgICAgICAgTWFrZSA9IGVjYXJzJE1ha2UsDQogICAgICAgICAgICAgICAgIFByaWNlID0gZWNhcnMkUHJpY2UvMTAwMCwgDQogICAgICAgICAgICAgICAgIFByZWRpY3RlZF9wcmljZSA9ICh0ZXN0Ml8yX2RvbGxhcnNbLDFdLzEwMDApLA0KICAgICAgICAgICAgICAgICBQcmVkaWN0ZWRfcHJpY2VfbHdyID0gKHRlc3QyXzJfZG9sbGFyc1ssMl0vMTAwMCksDQogICAgICAgICAgICAgICAgIFByZWRpY3RlZF9wcmljZV91cHIgPSAodGVzdDJfMl9kb2xsYXJzWywzXS8xMDAwKSwNCiAgICAgICAgICAgICAgICAgQ29uZmlkZW5jZV9wcmljZV9sd3IgPSAodGVzdDNfMl9kb2xsYXJzWywyXS8xMDAwKSwNCiAgICAgICAgICAgICAgICAgQ29uZmlkZW5jZV9wcmljZV91cHIgPSAodGVzdDNfMl9kb2xsYXJzWywzXSkvMTAwMCkNCnRlc3QyXzJfZG9sbGFyc25ldw0KYGBgDQpgYGB7cn0NCiMgY2FycyBncm91cHMgYnkgYnJhbmRzIHdpdGggdGhlIG1vc3QgbW9kZWxzDQoNCm1vc3RfbWFrZXMgPSB0ZXN0Ml8yX2RvbGxhcnNuZXcgJT4lIGdyb3VwX2J5KE1ha2UpICU+JQ0KICBmaWx0ZXIobigpID49IDEwKSAlPiUNCiAgc3VtbWFyaXNlKGF2ZXJhZ2VfY29zdCA9IChtZWFuKFByaWNlKSksIGF2ZXJhZ2VfcHJlZGljdGVkX2Nvc3QgPSAobWVhbihQcmVkaWN0ZWRfcHJpY2UpKSkNCmBgYA0KDQpgYGB7cn0NCnRlc3QgPSBnZ3Bsb3QoZWNhcnMsIGFlcyh4ID0gUHJpY2UsIHkgPSBmYWN0b3IoMCkpKSArDQogICAgICBnZW9tX2JveHBsb3QoKSsNCiAgICAgIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArDQogICAgICBnZ3RpdGxlKCdCb3ggUGxvdCBvZiBTZWxlY3RlZCBGZWF0dXJlJykgDQp0ZXN0DQpgYGANCg0KDQpgYGB7cn0NCg0KDQpncGx0MSA9IGdncGxvdChOVUxMLCBhZXMoUHJlZGljdGVkX3ByaWNlLCBQcmljZSkpICsNCiAgICAgIGdlb21fbGluZShkYXRhID0gdGVzdDJfMl9kb2xsYXJzbmV3LCBhZXMoeCA9IFByZWRpY3RlZF9wcmljZSwgeSA9IFByZWRpY3RlZF9wcmljZSkpICsNCiAgICAgIGdlb21fbGluZShkYXRhID0gdGVzdDJfMl9kb2xsYXJzbmV3LCBhZXMoeCA9IFByZWRpY3RlZF9wcmljZSwgeSA9IFByZWRpY3RlZF9wcmljZV9sd3IpLCBjb2wgPSAncmVkJykgKw0KICAgICAgZ2VvbV9saW5lKGRhdGEgPSB0ZXN0Ml8yX2RvbGxhcnNuZXcsIGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gUHJlZGljdGVkX3ByaWNlX3VwciksIGNvbCA9ICdyZWQnKSArDQogICAgICBnZW9tX2xpbmUoZGF0YSA9IHRlc3QyXzJfZG9sbGFyc25ldywgYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBDb25maWRlbmNlX3ByaWNlX2x3ciksIGNvbCA9ICdibHVlJykgKw0KICAgICAgZ2VvbV9saW5lKGRhdGEgPSB0ZXN0Ml8yX2RvbGxhcnNuZXcsIGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gQ29uZmlkZW5jZV9wcmljZV91cHIpLCBjb2wgPSAnYmx1ZScpICsNCiAgICAgIHlsaW0oMCwyNTApKyANCmdlb21fcG9pbnQoZGF0YSA9IHRlc3QyXzJfZG9sbGFyc25ldywgYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBQcmljZSksIGFscGhhID0gLjUpICsNCmdlb21fcG9pbnQoZGF0YSA9IG1vc3RfbWFrZXMsIGFlcyh4ID0gYXZlcmFnZV9wcmVkaWN0ZWRfY29zdCwgeSA9IGF2ZXJhZ2VfY29zdCksIHNpemUgPSAzLCBzaGFwZSA9IDIzLCBmaWxsID0gbWFrZV9jb2xvcnMpICsNCiBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbWFrZV9jb2xvcnMpDQoNCmdwbHQxDQoNCmdnc2F2ZSgnZ3BsdDEucG5nJywgd2lkdGggPSAxNSkNCiAgICAgICAgIA0KYGBgDQpgYGB7cn0NCmdwbHQxID0gZ2dwbG90KE5VTEwsIGFlcyhQcmVkaWN0ZWRfcHJpY2UsIFByaWNlKSkgKw0KICAgICAgZ2VvbV9saW5lKGRhdGEgPSB0ZXN0Ml8yX2RvbGxhcnNuZXcsIGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gUHJlZGljdGVkX3ByaWNlKSkgKw0KICAgICAgZ2VvbV9saW5lKGRhdGEgPSB0ZXN0Ml8yX2RvbGxhcnNuZXcsIGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gUHJlZGljdGVkX3ByaWNlX2x3ciksIGNvbCA9ICdyZWQnKSArDQogICAgICBnZW9tX2xpbmUoZGF0YSA9IHRlc3QyXzJfZG9sbGFyc25ldywgYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBQcmVkaWN0ZWRfcHJpY2VfdXByKSwgY29sID0gJ3JlZCcpICsNCiAgICAgIGdlb21fbGluZShkYXRhID0gdGVzdDJfMl9kb2xsYXJzbmV3LCBhZXMoeCA9IFByZWRpY3RlZF9wcmljZSwgeSA9IENvbmZpZGVuY2VfcHJpY2VfbHdyKSwgY29sID0gJ2JsdWUnKSArDQogICAgICBnZW9tX2xpbmUoZGF0YSA9IHRlc3QyXzJfZG9sbGFyc25ldywgYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBDb25maWRlbmNlX3ByaWNlX3VwciksIGNvbCA9ICdibHVlJykgKw0KICAgICAgeWxpbSgwLDI1MCkrIA0KICAgICAgZ2VvbV9wb2ludChkYXRhID0gdGVzdDJfMl9kb2xsYXJzbmV3LCBhZXMoeCA9IFByZWRpY3RlZF9wcmljZSwgeSA9IFByaWNlKSwgYWxwaGEgPSAuNSkgKw0KICAgICAgZ2VvbV9wb2ludChkYXRhID0gbW9zdF9tYWtlcywgYWVzKHggPSBhdmVyYWdlX3ByZWRpY3RlZF9jb3N0LCB5ID0gYXZlcmFnZV9jb3N0KSwgc2l6ZSA9IDMsIHNoYXBlID0gMjMsIGZpbGwgPSBtYWtlX2NvbG9ycykgKw0KICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ha2VfY29sb3JzKQ0KDQpgYGANCg0KYGBge3J9DQp0ZXN0Ml8yX2RvbGxhcnNuZXcgJT4lDQogIGFycmFuZ2UoUHJlZGljdGVkX3ByaWNlKQ0KYGBgDQpgYGB7cn0NCmVjYXJzDQoNCg0KcGxvdF9seSgNCiAgZGF0YSA9IGVjYXJzX21ha2UsDQogIHggPSB+UHJpY2UsDQogIHkgPSB+TWFrZSwNCiAgdHlwZSA9ICJib3giLA0KICBjb2xvciA9IH5NYWtlLA0KICBjb2xvcnMgPSBtYWtlX2NvbG9ycywNCiAgdGV4dCA9IH5DYXJfbmFtZSwNCiAgdG9vbHRpcCA9IGMoIngiLCAidGV4dCIpLA0KICBzaG93bGVnZW5kID0gRkFMU0UNCikNCg0KDQpwbG90X2x5KA0KICBkYXRhID0gZWNhcnNfbWFrZSwNCiAgeCA9IH5QcmljZSwNCiAgdHlwZSA9ICJib3giLA0KICB0ZXh0ID0gfkNhcl9uYW1lLA0KICBuYW1lID0gJycsDQogIHRvb2x0aXAgPSBjKCJ4IiwgInRleHQiKSklPiUgDQogIGxheW91dCh0aXRsZSA9ICJCb3ggUGxvdCBvZiBTZWxlY3RlZCBGZWF0dXJlIiwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICcnKSwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICcnKSkNCmBgYA0KYGBge3J9DQplY2Fyc1ssNV0NCmBgYA0KDQpgYGB7cn0NCm9wdGlvbnMocmVwci5wbG90LndpZHRoID0gMTUsIHJlcHIucGxvdC5oZWlnaHQgPTIpIA0KDQpnZ3Bsb3QoZGF0YSA9IHRlc3QyXzJfZG9sbGFyc25ldywgYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBQcmljZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gUHJlZGljdGVkX3ByaWNlKSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBQcmVkaWN0ZWRfcHJpY2UsIHkgPSBQcmVkaWN0ZWRfcHJpY2VfbHdyKSwgY29sID0gJ3JlZCcpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gUHJlZGljdGVkX3ByaWNlX3VwcikpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gUHJlZGljdGVkX3ByaWNlLCB5ID0gQ29uZmlkZW5jZV9wcmljZV9sd3IpKSArDQogIGdlb21fbGluZShhZXMoeCA9IFByZWRpY3RlZF9wcmljZSwgeSA9IENvbmZpZGVuY2VfcHJpY2VfdXByKSkgIysNCiBnZW9tX3BvaW50KGFlcyh4ID0gbW9zdF9tYWtlcyRhdmVyYWdlX2Nvc3QsIHkgPW1vc3RfbWFrZXMkYXZlcmFnZV9wcmVkaWN0ZWRfY29zdCkpDQoNCg0KICANCm5ldw0KYGBgDQoNCg0KYGBge3J9DQpuZXcNCm5ldyAlPiUgZ3JvdXBfYnkoTWFrZSkgJT4lDQogIGZpbHRlcihuKCkgPj0gMTApICU+JQ0KICBzdW1tYXJpc2UoYXZlcmFnZV9jb3N0ID0gKG1lYW4oUHJpY2UpLzEwMDApLCBhdmVyYWdlX3ByZWRpY3RlZF9jb3N0ID0gKG1lYW4oUHJlZGljdGVkX3ByaWNlKS8xMDAwKSkgIyU+JQ0KICAjZ2dwbG90KC4sIGFlcyh4ID0gTWFrZSwgeSA9IGF2ZXJhZ2VfcHJlZGljdGVkX2Nvc3QpKSArDQogICNnZW9tX2NvbChhZXMoZmlsbCA9IE1ha2UpKSArIA0KICAjeWxhYignQXZlcmFnZSBjb3N0IGluIEdlcm1hbnkgaW4gdGhvdXNhbmRzIG9mIEVydXJvcycpKw0KICAjdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICMgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAjICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpDQpgYGANCmBgYHtyfQ0KbmV3ICU+JSBncm91cF9ieShNYWtlKSAlPiUNCiAgZmlsdGVyKG4oKSA+PSAxMCkgJT4lDQogIHN1bW1hcmlzZShhdmVyYWdlX3ByaWNlID0gKG1lYW4oUHJpY2UpLzEwMDApLCBhdmVyYWdlX3ByZWRpY3RlZF9wcmljZSA9ICAobWVhbihQcmVkaWN0ZWRfcHJpY2UpLzEwMDApKSU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBhdmVyYWdlX3ByZWRpY3RlZF9wcmljZSwgeSA9IGF2ZXJhZ2VfcHJpY2UpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gTWFrZSksIHNpemUgPTQpIA0KICANCmBgYA0KDQoNCg0KYGBge3J9DQpuZXcNCm5ldyAlPiUgZ3JvdXBfYnkoTWFrZSkgJT4lDQogIGZpbHRlcihuKCkgPj0gMTApICU+JQ0KICBzdW1tYXJpc2UoYXZlcmFnZV9wcmljZSA9IChtZWFuKFByaWNlKS8xMDAwKSwgYXZlcmFnZV9wcmVkaWN0ZWRfcHJpY2UgPSAobWVhbihQcmVkaWN0ZWRfcHJpY2UpLzEwMDApKSU+JQ0KICBnZ3Bsb3QoLiwgYWVzKHggPSBhdmVyYWdlX3ByZWRpY3RlZF9wcmljZSwgeSA9IGF2ZXJhZ2VfcHJpY2UpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gTWFrZSksIHNpemUgPTQpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gYXZlcmFnZV9wcmVkaWN0ZWRfcHJpY2UsIHkgPSBhdmVyYWdlX3ByZWRpY3RlZF9wcmljZSkpICsgDQoNCg0KYGBgDQoNCmBgYHtyfQ0KcHJlZGljdChtb2RlbCwgbmV3ZGF0YSwgaW50ZXJ2YWwgPSAnY29uZmlkZW5jZScpDQpwcmVkaWN0KG1vZGVsLCBuZXdkYXRhLCBpbnRlcnZhbCA9ICdwcmVkaWN0aW9uJykNCmBgYA0KDQoNCmBgYHtyfQ0KbmV3DQpuZXcgJT4lIGdyb3VwX2J5KE1ha2UpICU+JQ0KICBmaWx0ZXIobigpID49IDEwKSAlPiUNCiAgc3VtbWFyaXNlKGF2ZXJhZ2VfcHJpY2UgPSAobWVhbihQcmljZSkvMTAwMCksIGF2ZXJhZ2VfcHJlZGljdGVkX3ByaWNlID0gKG1lYW4oUHJlZGljdGVkX3ByaWNlKS8xMDAwKSkNCmBgYA0KDQpgYGB7cn0NCmVjYXJzX21pc3NpbmdfcHJpY2UNCnByZQ0KYGBgDQoNCg0KYGBge3J9DQptb2RlbA0KYGBgDQpgYGB7cn0NCmVjYXJzDQpgYGANCg0KDQpgYGB7cn0NCm1vZGVsLmVtcHR5ID0gbG0oUHJpY2VfcG93IH4gMSwgZGF0YSA9IGVjYXJzKQ0KbW9kZWwuZnVsbCA9IGxtKFByaWNlX3BvdyB+IEVmZmljaWVuY3lfcG93ICsgUmFuZ2UgKyBCYXR0ZXJ5ICsgU3BlZWRfcG93ICsgRmFzdF9jaGFyZ2UgKyBBY2NlbGVyYXRpb24sIGRhdGEgPSBlY2FycykNCnNjb3BlID0gbGlzdChsb3dlciA9IGZvcm11bGEobW9kZWwuZW1wdHkpLCB1cHBlciA9IGZvcm11bGEobW9kZWwuZnVsbCkpDQpzY29wZQ0KZm9yd2FyZEFJQyA9IHN0ZXAobW9kZWwuZW1wdHksIHNjb3BlLCBkaXJlY3Rpb24gPSAnZm9yd2FyZCcsIGsgPSAyKQ0KYGBgDQoNCmJhdHRlcnkgc3BlZWRfcG93IGVmZmljaWVuY3kgYW5kIGZhc3QgY2hhcmdlIA0KDQpgYGB7cn0NCm1vZGVsLmVtcHR5MiA9IGxtKFByaWNlIH4gMSwgZGF0YSA9IGVjYXJzKQ0KbW9kZWwuZnVsbDIgPSBsbShQcmljZSB+IEVmZmljaWVuY3kgKyBSYW5nZSArIEJhdHRlcnkgKyBUb3Bfc3BlZWQgKyBGYXN0X2NoYXJnZSArIEFjY2VsZXJhdGlvbiwgZGF0YSA9IGVjYXJzKQ0Kc2NvcGUyID0gbGlzdChsb3dlciA9IGZvcm11bGEobW9kZWwuZW1wdHkyKSwgdXBwZXIgPSBmb3JtdWxhKG1vZGVsLmZ1bGwyKSkNCnNjb3BlMg0KZm9yd2FyZEFJQzIgPSBzdGVwKG1vZGVsLmVtcHR5Miwgc2NvcGUyLCBkaXJlY3Rpb24gPSAnZm9yd2FyZCcsIGsgPSAyKQ0KYGBgDQoNCg0KYGBge3J9DQptb2RlbC5lbXB0eTMgPSBsbShQcmljZV9wb3cgfiAxLCBkYXRhID0gZWNhcnMpDQptb2RlbC5mdWxsMyA9IGxtKFByaWNlX3BvdyB+IEVmZmljaWVuY3kgKyBSYW5nZSArIEJhdHRlcnkgKyBUb3Bfc3BlZWQgKyBGYXN0X2NoYXJnZSArIEFjY2VsZXJhdGlvbiwgZGF0YSA9IGVjYXJzKQ0Kc2NvcGUzID0gbGlzdChsb3dlciA9IGZvcm11bGEobW9kZWwuZW1wdHkzKSwgdXBwZXIgPSBmb3JtdWxhKG1vZGVsLmZ1bGwzKSkNCmZvcndhcmRBSUMzID0gc3RlcChtb2RlbC5lbXB0eTMsIHNjb3BlMywgZGlyZWN0aW9uID0gJ2ZvcndhcmQnLCBrID0gMikNCmBgYA0KSSdtIGdldHRpbmcgYSBsb3dlciBBSUMgd2hlbiBJIHJ1biB0aGVzZSB3aXRob3V0IHRyYW5zZm9ybWluZyB0aGVtPz8/IEkgbmVlZCB0byB0cmFuc2Zvcm0gcHJpY2UgYnV0IG5vdCB0aGUgb3RoZXJzPz8gbm90IHN1cmUgd2hhdCB0byBkbz8/IA0KDQpgYGB7cn0NCm1vZGVsLmVtcHR5ID0gbG0oUHJpY2VfcG93IH4gMSwgZGF0YSA9IGVjYXJzKQ0KbW9kZWwuZnVsbCA9IGxtKFByaWNlX3BvdyB+IEVmZmljaWVuY3lfcG93ICsgUmFuZ2UgKyBCYXR0ZXJ5ICsgU3BlZWRfcG93ICsgRmFzdF9jaGFyZ2UgKyBBY2NlbGVyYXRpb24sIGRhdGEgPSBlY2FycykNCnNjb3BlID0gbGlzdChsb3dlciA9IGZvcm11bGEobW9kZWwuZW1wdHkpLCB1cHBlciA9IGZvcm11bGEobW9kZWwuZnVsbCkpDQpzY29wZQ0KZm9yd2FyZEFJQyA9IHN0ZXAobW9kZWwuZW1wdHksIHNjb3BlLCBkaXJlY3Rpb24gPSAnZm9yd2FyZCcsIGsgPSAyKQ0KYGBgDQoNCmBgYHtyfQ0KYnJvb206OmdsYW5jZShtb2RlbCkNCmJyb29tOjpnbGFuY2UobW9kZWwuZnVsbCkNCm1vZGVsX2Jlc3QgPSBsbShQcmljZV9wb3cgfiBFZmZpY2llbmN5X3BvdyArIFJhbmdlICsgQmF0dGVyeSArIFNwZWVkX3BvdyArIEZhc3RfY2hhcmdlLCBkYXRhID0gZWNhcnMpDQpicm9vbTo6Z2xhbmNlKG1vZGVsLmZ1bGwzKQ0KYnJvb206OmdsYW5jZShtb2RlbF9iZXN0KQ0KYGBgDQoNCg0KYGBge3J9DQplY2Fycw0KbW9kZWxfYm94ID0gbG0oUHJpY2UgfiBUb3Bfc3BlZWQgKyBSYW5nZSArIEVmZmljaWVuY3kgKyBGYXN0X2NoYXJnZSArIEFjY2VsZXJhdGlvbiwgZGF0YSA9IGVjYXJzKQ0Kc3VtbWFyeShtb2RlbF9ib3gpDQoNCmBgYA0KYGBge3J9DQpiYyA9IGJveENveChtb2RlbF9ib3gpDQoNCmxhbWJkYSA9IGJjJHhbd2hpY2goYmMkeSA9PSBtYXgoYmMkeSkpXQ0KbGFtYmRhDQpQcmljZS5iYyA9IChlY2FycyRQcmljZV5sYW1iZGEgLSAxKS9sYW1iZGENClByaWNlLmJjDQptb2RlbC5iYyA9IGxtKFByaWNlLmJjIH4gVG9wX3NwZWVkICsgUmFuZ2UgKyBFZmZpY2llbmN5ICsgRmFzdF9jaGFyZ2UgKyBBY2NlbGVyYXRpb24sIGRhdGEgPSBlY2FycykNCiAgICAgICAgICAgICAgDQpzdW1tYXJ5KG1vZGVsLmJjKQ0KYnJvb206OmdsYW5jZShtb2RlbC5iYykNCg0KaGlzdChQcmljZS5iYykNCmBgYA0KKioqKlRoaXMgaXMgaG93IHRvIHVuZG8gdGhlIGxhbWJkYSB0cmFuc2Zvcm1hdGlvbg0KYGBge3J9DQooKFByaWNlLmJjKmxhbWJkYSkgKyAxKV4oMS9sYW1iZGEpDQplY2FycyRQcmljZQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90Lm5ldygpDQpwbG90KCB4ID0gNTAsIHkgPSA1NCkNCmxpbmVzKHByZWRpY3RlZF9wcmljZSRQcmVkaWN0ZWQsIHByZWRpY3RlZF9wcmljZSRQcmVkaWN0ZWQpDQpgYGANCg0KYGBge3J9DQplY2Fyc19taXNzaW5nX3ByaWNlDQpgYGANCg0KDQoNCg0KDQoNClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIA0KDQpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIA0KDQpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouDQoNCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLg0KDQpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuDQo=